﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Web.Services.Protocols;
using Grain.Crm.Common;
using Grain.Crm.DataMigrator.Imports;
using System.Diagnostics;
using Grain.Crm.DataMigrator.CrmServices;
using Grain.Crm.DataMigrator.Properties;
using Grain.Crm.ExcelExtractor;
using Grain.Crm.ExcelExtractor.InputDescription;
using Grain.Crm.ExcelExtractor.InputDescription.Sheets;
using Grain.Crm.ExcelImporter;
using Grain.Crm.ExcelProcessor;

namespace Grain.Crm.DataMigrator
{

    public class ImportsJob
    {
        static void Main(string[] args)
        {
            try
            {
                Console.WriteLine("ExcelImporter v1.0 \n");

                #region Initialization

                ProfileSheetDescription profileDesc;
                SkillsSheetDescription skillsDesc;
                WorkingExperienceSheetDescription workingExperienceSheetDescription;
                ProjectExperienceSheetDescription projectExperienceSheetDescription;
                CoursesSheetDescription coursesSheetDescription;
                EducationSheetDescription educationSheetDescription;

                SheetsManager.BuildDescriptions(out profileDesc, out skillsDesc, out workingExperienceSheetDescription,
                    out projectExperienceSheetDescription, out coursesSheetDescription, out educationSheetDescription);

                var payloads = new List<ImportPayload>();
                var serviceUrl = Settings.Default.Grain_Crm_DataMigrator_CrmServices_CrmServer;
                var filename = Settings.Default.SheetFile;
                var org = Settings.Default.CrmOrganization;
                var user = Settings.Default.ServiceUser;
                var pwd = Settings.Default.ServicePassword;
                var domain = Settings.Default.Domain;
                ValueDescription.SheetCulture = Thread.CurrentThread.CurrentCulture.Name;
                
                EnumerableRowCollection<DataRow> profileCollection, skillsCollection, workingExpCollection, projectCollection,coursesCollection,educationCollection;

              
                var filePath = Path.Combine(Helper.AssemblyDirectory, filename);

                #endregion

                Console.WriteLine("Parsing sheet file '" + filePath + "'");

                #region Parse 'Profile' sheet & set Language - IS REQUIRED!
                XlsProcessor.QueryData(filePath, profileDesc.SheetName, out profileCollection);

                ImportsGlobal.Language = XlsValueRetriever.GetValueByDescription(profileCollection, profileDesc.Descriptions.GetByXlsValueName("CvLanguage"));


                payloads.Add(ImportPayloadGenerator.GeneratePayload(profileDesc, profileCollection,
                                                                    EntityName.contact.ToString(), filename));
                payloads.Add(ImportPayloadGenerator.GeneratePayload(profileDesc, profileCollection,
                                                                    EntityName.new_curriculumvitae.ToString(), filename));
                payloads.Add(ImportPayloadGenerator.GeneratePayload(profileDesc, profileCollection,
                                                                    EntityName.new_contactlanguage.ToString(), filename));
                #endregion

                #region Parse 'Skills' sheet
                XlsProcessor.QueryData(filePath, skillsDesc.SheetName, out skillsCollection);
                payloads.Add(ImportPayloadGenerator.GeneratePayload(skillsDesc, skillsCollection,
                                                                    EntityName.new_contactskill.ToString(), filename));

                #endregion

                #region Parse 'Working experience sheet'

                XlsProcessor.QueryData(filePath, workingExperienceSheetDescription.SheetName, out workingExpCollection);
                payloads.Add(ImportPayloadGenerator.GeneratePayload(workingExperienceSheetDescription, workingExpCollection,
                                                                    EntityName.new_professionalexperience.ToString(), filename));
                #endregion

                #region Parse 'Project experience sheet'

                XlsProcessor.QueryData(filePath, projectExperienceSheetDescription.SheetName, out projectCollection);
                payloads.Add(ImportPayloadGenerator.GeneratePayload(projectExperienceSheetDescription, projectCollection,
                                                                    EntityName.new_contactprojects.ToString(), filename));
                #endregion

                #region Parse 'Courses&Certifications sheet'

                XlsProcessor.QueryData(filePath, coursesSheetDescription.SheetName, out coursesCollection);
                payloads.Add(ImportPayloadGenerator.GeneratePayload(coursesSheetDescription, coursesCollection,
                                                                    EntityName.new_contactcourses.ToString(), filename));
                #endregion

                #region Parse 'Education sheet'

                XlsProcessor.QueryData(filePath, educationSheetDescription.SheetName, out educationCollection);
                payloads.Add(ImportPayloadGenerator.GeneratePayload(educationSheetDescription, educationCollection,
                                                                    EntityName.new_education.ToString(), filename));
                #endregion

                Console.WriteLine("Parsing done.");

                var result = Run(serviceUrl, org, domain, user, pwd,
                                                     ImportsGlobal.Language, payloads);

                if (result.AllImportsSucceed)
                {
                    Console.ForegroundColor = ConsoleColor.Green;
                    Console.WriteLine("\n>> Finished. All imports succeed.");
                }
                else
                {
                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.WriteLine("\n>> Finished. At least one import failed.");
                }

                Console.WriteLine("\n -- Press any key to exit --");
                Console.ReadLine();
            }
            catch(Exception ex)
            {
                Console.WriteLine("\nAn error has occured. \n\nMessage:\n" + ex.Message + "\n\nDetails:\n" + ex.ToString());

                Console.WriteLine("\nPress <enter> to exit..");
                Console.ReadLine();
            }
        }

        public static ImportsResult Run(string crmServerUrl, string orgName,
            string domain, string username, string password, string language, IEnumerable<ImportPayload> data)
        {
            #region Setup service

            Console.WriteLine("Starting import. Language:" + ImportsGlobal.Language);
            Console.WriteLine("Connecting to Crm service..");
            
            CrmService service;

            if (!Settings.Default.UseIFD)
                service = CrmServiceUtility.GetCrmService(crmServerUrl + Settings.Default.CrmServicePath, orgName, domain, username, password);
            else
            {
                var dicso = new IFDConnection(orgName, crmServerUrl, domain, username, password);
                 service = dicso.CrmService;
            }

            Console.WriteLine("Connected.");

            var who = new WhoAmIRequest();

            Console.WriteLine("Retrieving crm user..");
            var whoResponse = (WhoAmIResponse)service.Execute(who);
            Console.WriteLine("Crm user retrieved: userID: " + whoResponse.UserId.ToString());
            #endregion

            var result = new ImportsResult();
            result.AllImportsSucceed = true;
            Exception ex;
            bool success = true;

            foreach (var dataItem in data)
            {
                var import = ImportFactory.Create(service, whoResponse, dataItem);

                success = import.Execute(out ex);
                if (ex != null) PrintException(ex);

                if (!success)
                {
                    ConsoleLog.Error("There was an error during this import. Skipping others.");
                    result.AllImportsSucceed = false;

                    return result;
                }

               
                result.AllImportsSucceed &= success;
                if (ex != null)
                    result.Exceptions.Add(ex);

            }

            return result;
        }

        private static void PrintException(Exception ex)
        {
            Console.ForegroundColor = ConsoleColor.Red;

            var soapException = ex as SoapException;
            if (soapException != null)
            {
                Console.WriteLine("There was a Soap exception.");
                Console.WriteLine(soapException.Message);
                Console.WriteLine(soapException.Detail.InnerText);
            }
            else
            {
                Console.WriteLine("There was an application exception.");
                Console.WriteLine(ex.ToString());

                // Display the details of the inner exception.
                if (ex.InnerException != null)
                {
                    Console.WriteLine(ex.InnerException.Message);

                    SoapException se = ex.InnerException as SoapException;
                    if (se != null)
                        Console.WriteLine(se.Detail.InnerText);

                }
            }
            Console.ResetColor();
        }

    }
}
